#include "ztboxpluginloader.h"

#include <QDebug>
#include <QDir>
#include <QPluginLoader>
#include <QStandardPaths>
#include <configutil.h>

ZTBoxPluginLoader::ZTBoxPluginLoader(QObject *parent)
    : QObject{parent}
{

}

ZTBoxPluginLoader &ZTBoxPluginLoader::instance()
{
    static ZTBoxPluginLoader loader;
    return loader;
}

/**
 * @brief ZTBoxPluginLoader::pluginLoader
 * @param dir
 */
void ZTBoxPluginLoader::pluginLoader(QString path)
{
    QFileInfo pathInfo(path);
    if (!path.isEmpty()) {
        if (pathInfo.isFile()) {
            if (path.endsWith(".so")) {
                loadPluginFile(path);
            }
        }
        if(pathInfo.isDir()) {
            loadPluginDir(path);
        }
    } else {
        loadPluginDir(ConfigUtil::userPluginsDir());
    }

    pluginLoadedSignal(plugins());
}

/**
 * @brief ZTBoxPluginLoader::loadPluginFile
 * @param pluginFilePath
 */
ZTBoxInterface* ZTBoxPluginLoader::loadPluginFile(const QString &pluginFilePath, bool skipAppend)
{
    ZTBoxInterface *extension = nullptr;

    // 加载插件
    qDebug() << "loading:" << pluginFilePath;
    QPluginLoader pluginLoader(pluginFilePath);
    if (pluginLoader.load()) {
        QObject *plugin = pluginLoader.instance();
        // 使用插件对象进行相关操作
        extension = qobject_cast<ZTBoxInterface*>(plugin);
        if (extension) {
            if (!skipAppend) appendPlugins(extension);
            qDebug() << "loaded plugin: " << extension->PluginName() << QString("(%1}").arg(pluginFilePath);
        }
    } else {
        qDebug() << "Failed to load plugin: " << pluginLoader.errorString();
    }

    return extension;
}

void ZTBoxPluginLoader::loadPluginDir(QDir pluginDir)
{
    QStringList soFiles = pluginDir.entryList(QDir::Files | QDir::NoDotAndDotDot);
    foreach (const QString &soFile, soFiles) {
        if (soFile.endsWith(".so")) {
            // 加载插件
            loadPluginFile(pluginDir.absoluteFilePath(soFile));
        }
    }
}

void ZTBoxPluginLoader::loadPluginDirPath(QString pluginDirPath)
{
    loadPluginDir(QDir(pluginDirPath));
}

/**
 * @brief ZTBoxPluginLoader::appendPlugins
 * @param newPlugin
 */
void ZTBoxPluginLoader::appendPlugins(ZTBoxInterface *newPlugin)
{
    m_plugins.append(newPlugin);
    emit pluginsChanged(newPlugin);
}

/**
 * @brief ZTBoxPluginLoader::plugins
 * @return
 */
QList<ZTBoxInterface *> ZTBoxPluginLoader::plugins() const
{
    return m_plugins;
}
